﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SignInServer.Server.Configuration;
using SignInServer.Server.Tools;

namespace SignInServer.Server
{
    /// <summary>
    /// 单个与客户端的连接
    /// </summary>
    class ClientConn
    {
        /// <summary>
        /// 该连接在链接池中的索引
        /// </summary>
        public int connIndex;
        /// <summary>
        /// 该连接的socket
        /// </summary>
        public Socket connSocket;
        /// <summary>
        /// 该连接是否正在使用
        /// </summary>
        public bool connStatus;
        /// <summary>
        /// 拆包类
        /// </summary>
        private UnpackMessage unpackMessage;
        /// <summary>
        /// 连接缓冲区
        /// </summary>
        private byte[] connReadBuff;
        /// <summary>
        /// 缓冲区使用大小
        /// </summary>
        private int connReadBuffUseCount;
        /// <summary>
        /// 分类处理消息中心
        /// </summary>
        private SwitchMessage switchMessage;

        public ClientConn(int index)
        {
            connIndex = index;
            connStatus = false;
        }
        /// <summary>
        /// 开启与客户端的连接
        /// </summary>
        /// <param name="socket"></param>
        public void OpenConn(Socket socket)
        {
            connSocket = socket;
            connStatus = true;
            unpackMessage = new UnpackMessage();
            connReadBuff = new byte[SocketConfiguration.BUFF_SIZE];
            switchMessage = new SwitchMessage(this);
            connReadBuffUseCount = 0;

            Console.WriteLine("[" + GetClientAddress() + "] 连接到服务器，索引地址:" + connIndex);

            connSocket.BeginReceive(connReadBuff, 0, getBuffRemain(), SocketFlags.None, ConnReceiveCb, null);
        }
        /// <summary>
        /// 因错误而关闭连接
        /// </summary>
        public void ErrorCloseConn()
        {
            Console.WriteLine("链接池引索为:" + connIndex + "的连接因错误而关闭");
            ClearConnData();
        }
        /// <summary>
        /// 因客户端请求或服务器命令关闭连接
        /// </summary>
        public void CloseConn()
        {
            Console.WriteLine("链接池引索为:" + connIndex + "的连接已正常关闭");
            ClearConnData();
        }
        /// <summary>
        /// 关闭连接，清除数据,减少内存占用
        /// </summary>
        public void ClearConnData()
        {
            connSocket = null;
            connStatus = false;
            unpackMessage = null;
            connReadBuff = null;
            switchMessage = null;
            Console.WriteLine("链接池引索为:" + connIndex + "的数据已清理");
        }
        /// <summary>
        /// 获取该连接的客户端ip
        /// </summary>
        /// <returns></returns>
        public string GetClientAddress()
        {
            if (!connStatus)
                return null;
            return connSocket.RemoteEndPoint.ToString();
        }

        public void SendMessage(int type,byte[] data)
        {
            PackMessage pack = new PackMessage(type, data);
            connSocket.Send(pack.getPackData());
        }
        /// <summary>
        /// 添加缓冲区使用数
        /// </summary>
        /// <param name="count"></param>
        private void AddReadBuffUseCount(int count)
        {
            connReadBuffUseCount += count;
        }

        /// <summary>
        /// 向解包类的原始数据链表添加数据
        /// </summary>
        public void addDataToUnpack()
        {
            unpackMessage.AddInitialData(ConvertTypeTool.CutByteArrayFromArrayToAnother(connReadBuff, 0, connReadBuffUseCount));
            connReadBuffUseCount = 0;
        }
        /// <summary>
        /// 处理原始数据链表中的信息
        /// </summary>
        private void ProcessingData()
        {
            while (true)
            {
                BasicMessage basicMessage = unpackMessage.processingInitialData();
                if (basicMessage == null)
                {
                    break;
                }
                else
                {
                    switchMessage.switchMessageManager(basicMessage);
                }

            }
        }

        /// <summary>
        /// 该连接的接收/处理函数(为使整个服务器获得更好的性能将每个客户端连接的操作集合为一个线程)
        /// </summary>
        /// <param name="asyncResult"></param>
        private void ConnReceiveCb(IAsyncResult asyncResult)
        {
            try
            {
                Thread.Sleep(500);
                int count = connSocket.EndReceive(asyncResult);
                if (count == 0)
                {
                ErrorCloseConn(); return;
                }

                AddReadBuffUseCount(count);
                addDataToUnpack();
                Console.WriteLine("链接池引索为:" + connIndex + "的连接接收到数据-长度:"+count);
            }
            catch (Exception ex)
            {
                Console.WriteLine("链接池引索为:" + connIndex + "的连接在接收时报告了一个错误并且关闭;错误:" + ex.Message);
                ErrorCloseConn();

            }
            try
            {
                ProcessingData();
            }
            catch (Exception ex)
            {
                Console.WriteLine("链接池引索为:" + connIndex + "的连接在处理数据时报告了一个错误;错误:" + ex.Message);
           }
            connSocket.BeginReceive(connReadBuff, 0, getBuffRemain(), SocketFlags.None, ConnReceiveCb, null);
        }

        private int getBuffRemain()
        {
            return SocketConfiguration.BUFF_SIZE - connReadBuffUseCount;
        }
    }
}
